Skip to content

Fix ConcurrentModificationException in CacheableRegistry on Folia/CanvasMC servers#243

Open
twisti-dev wants to merge 1 commit intoturikhay:mainfrom
SLNE-Development:main
Open

Fix ConcurrentModificationException in CacheableRegistry on Folia/CanvasMC servers#243
twisti-dev wants to merge 1 commit intoturikhay:mainfrom
SLNE-Development:main

Conversation

@twisti-dev
Copy link

Problem

When players join a Folia or CanvasMC server, a ConcurrentModificationException is thrown in CacheableRegistry.getId():

java.util.ConcurrentModificationException
    at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1230)
    at MapModCompanion.jar//...spigot.IdRegistry$CacheableRegistry.getId(IdRegistry.java:26)
    at MapModCompanion.jar//...spigot.XaeroHandler.sendPacket(XaeroHandler.java:67)
    at MapModCompanion.jar//...spigot.XaeroHandler.onPlayerJoined(XaeroHandler.java:56)

Folia (and forks like CanvasMC) uses regionized multithreading, meaning PlayerJoinEvent can be fired concurrently from different region tick threads. The CacheableRegistry cache was backed by a plain HashMap, which is not thread-safe. Concurrent calls to HashMap.computeIfAbsent() from multiple threads cause a ConcurrentModificationException.

Full log: https://mclo.gs/bYg8IkD

Fix

Replace HashMap with ConcurrentHashMap in CacheableRegistry:

- private final Map<String, Integer> cache = new HashMap<>();
+ private final Map<String, Integer> cache = new ConcurrentHashMap<>();

ConcurrentHashMap.computeIfAbsent() is atomic and thread-safe, which prevents the concurrent modification issue on multi-threaded server implementations.

Impact

  • Fixes exception on player join for Folia, CanvasMC, and other regionized server forks.
  • No behavioral change on standard Spigot/Paper servers (single-threaded tick loop).

Copilot AI review requested due to automatic review settings March 22, 2026 10:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a ConcurrentModificationException occurring on Folia/CanvasMC (regionized multithreading) by making IdRegistry.CacheableRegistry’s internal cache thread-safe.

Changes:

  • Replaced the non-thread-safe HashMap cache with a ConcurrentHashMap in CacheableRegistry.
  • Updated imports accordingly.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants